package com.wootion.cims.module.communityresidence.household.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.wootion.cims.dao.*;
import com.wootion.cims.general.utils.GetIp;
import com.wootion.cims.module.communitypersonal.model.Person;
import com.wootion.cims.module.communityresidence.household.dto.HouseholdDto;
import com.wootion.cims.module.communityresidence.household.dto.PageQueryHouse;
import com.wootion.cims.module.communityresidence.household.excel.ExcelDto;
import com.wootion.cims.module.communityresidence.household.service.HouseholdService;
import com.wootion.cims.module.communityresidence.occupancy.dto.OccupancyDto;
import com.wootion.cims.module.communityresidence.occupancy.excel.ExcelRules;
import com.wootion.cims.module.communityresidence.residencelist.model.Residence;
import com.wootion.cims.module.communityservice.dto.PersonDto;
import com.wootion.cims.module.systemsetting.community.model.SysCommunity;
import com.wootion.cims.module.systemsetting.log.model.SysLog;
import com.wootion.cims.module.systemsetting.polt.model.SysPlot;
import com.wootion.cims.module.systemsetting.user.model.SysUserRole;
import com.wootion.cims.module.systemsetting.user.model.User;
import com.wootion.cims.response.ResponseResult;
import com.wootion.cims.response.ResultCode;
import com.wootion.cims.shiro.utils.ShiroUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: LanQiang
 * @Date: 2022/12/23/8:40
 * @Description: 作用xxx
 */
@Slf4j
@Service
public class HouseholdServiceImpl implements HouseholdService {
    @Resource
    private SysUserRoleDao sysUserRoleDao;
    @Resource
    private SysRoleDao sysRoleDao;
    @Resource
    private SysUserCommunityDao sysUserCommunityDao;
    @Resource
    private ResidenceDao residenceDao;
    @Resource
    private SysCommunityDao sysCommunityDao;
    @Resource
    private SysPlotDao sysPlotDao;
    @Resource
    private PersonDao personDao;
    @Value("${cims.path}")
    private String basePath;
    @Resource
    private SysLogDao sysLogDao;
    /**
     * 户籍情况列表
     * @param pageQueryHouse
     * @return
     */
    @Override
    public ResponseResult list(PageQueryHouse pageQueryHouse) {
        ExcelRules excelRules = pageQueryHouse.getCondition();
        Integer page = pageQueryHouse.getPage();
        Integer limit = pageQueryHouse.getLimit();
        if(Objects.isNull(page) || Objects.isNull(limit)){
            return ResponseResult.builder().code(ResultCode.SYSTEM_ERROR.getCode()).message("页码数和每页显得的天数不能为空").build();
        }
        //筛查人数范围内的业主的id
        //拿到所有符合入住人数范围的住宅id
        List<String> resids = new ArrayList<>();
        //拿到所有符合入住人数范围房屋id
        List<Map<String,Object>> maps = new ArrayList<>();
        if(excelRules != null && excelRules.getMinNumber()!=null && excelRules.getMaxNumber() != null){
            if(excelRules.getMinNumber() == 0){
                List<Map<String, Object>> maps1 = residenceDao.countPlaceIdIsNull();
                for (Map<String, Object> map : maps1) {
                    String abodeId = (String) map.get("place_id");
                    if(!StringUtils.hasText(abodeId)){//拿到全部为空的住宅id
                        String id = (String) map.get("id");
                        resids.add(id);
                    }
                }
            }
            //先查询符合条件的房屋id,以及统计当前房屋中的人数
            maps = residenceDao.countNumberPersonPlace(excelRules.getMinNumber(), excelRules.getMaxNumber());
            if(maps.size()<=0){
                PageDTO<HouseholdDto> dtoPageDTO = new PageDTO<>();
                dtoPageDTO.setCurrent(page);
                dtoPageDTO.setSize(limit);
                return ResponseResult.builder().data(dtoPageDTO).build();
            }
            for (Map<String, Object> map : maps) {
                String id = (String) map.get("id");
                resids.add(id);
            }
        }
        //特殊处理楼房的详细地址
        String newDetailedAddress2 = null;
        if(excelRules != null && excelRules.getDetailedAddress() != null){
            if(excelRules.getDetailedAddress().size()>1){
                List<String> detailedAddress = excelRules.getDetailedAddress();
                newDetailedAddress2  =  detailedAddress.get(0) +"/"+ detailedAddress.get(1);
            }else{
                List<String> detailedAddress = excelRules.getDetailedAddress();
                newDetailedAddress2 = detailedAddress.get(0);
            }
        }
        String keyWord = null;
        String residenceClasses = null;
        String residenceCategory = null;
        String communityId = null;
        String plotId = null;
        String detailedAddress = null;
        String houseNumber = null;
        assert excelRules != null;
        keyWord = excelRules.getKeyWord();//关键字
        residenceClasses = excelRules.getResidenceClasses();//住宅类别
        residenceCategory = excelRules.getResidenceCategory();//房屋类别
        communityId = excelRules.getCommunityId();//社区id
        plotId = excelRules.getPlotId();//小区id
        detailedAddress = newDetailedAddress2;//详细地址
        houseNumber = excelRules.getHouseNumber();//门牌号
        //获取当前登陆人的信息
        User user = (User) ShiroUtils.getSubject().getPrincipal();
        LambdaQueryWrapper<SysUserRole> lambdaQueryWrapper5 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper5.eq(SysUserRole::getUserId, user.getId());
        SysUserRole sysUserRole = sysUserRoleDao.selectOne(lambdaQueryWrapper5);
        String roleKey = sysRoleDao.findByRoles(sysUserRole.getRoleId());
        PageDTO<HouseholdDto> dtoPageDTO;
        //街道管理员的情况下
        if("street:admin".equals(roleKey)){
            PageDTO<HouseholdDto> pageDTO = new PageDTO<>(page,limit);
            dtoPageDTO = residenceDao.findListHouse(pageDTO, null, resids, keyWord, residenceClasses, residenceCategory, communityId, plotId, detailedAddress, houseNumber);
        }else{
            //如果是社区管理员
            List<String> commnityIds = sysUserCommunityDao.commnityIds(user.getId());
            if (Objects.isNull(commnityIds) || commnityIds.size() <= 0) {
                return ResponseResult.builder().message("当前用户还没有任何社区权限").build();
            }
            PageDTO<HouseholdDto> pageDTO = new PageDTO<>(page, limit);
            dtoPageDTO = residenceDao.findListHouse(pageDTO, commnityIds, resids, keyWord, residenceClasses, residenceCategory, communityId, plotId, detailedAddress, houseNumber);
        }
        //开始处理入户籍成员名称和户籍成员人数
        List<HouseholdDto> records = dtoPageDTO.getRecords();
        for (HouseholdDto record : records) {
            //处理业主姓名
            if(StringUtils.hasText(record.getOwnerId())){
                LambdaQueryWrapper<Person> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
                lambdaQueryWrapper1.eq(Person::getId,record.getOwnerId());
                lambdaQueryWrapper1.eq(Person::getEnabled,true);
                Person person = personDao.selectOne(lambdaQueryWrapper1);
                if(Objects.isNull(person)){
                    record.setPersonName(null);//业主姓名
                }else {
                    record.setPersonName(person.getName());//业主姓名
                }
            }else{
                record.setPersonName(null);
            }
            LambdaQueryWrapper<Person> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(Person::getPlaceId, record.getId());//房屋下的户籍人员
            lambdaQueryWrapper.eq(Person::getEnabled,true);
            //处理户籍人员姓名
            List<Person> peoples = personDao.selectList(lambdaQueryWrapper);
            List<String> names = new ArrayList<>();
            if (!Objects.isNull(peoples) && peoples.size() > 0) {
                for (Person people : peoples) {
                    names.add(people.getName());
                }
                record.setHouseholdMember(names);
                record.setHouseholdMemberNumber((long) record.getHouseholdMember().size());//户籍人员数
            } else {
                record.setHouseholdMember(null);
                record.setHouseholdMemberNumber(0L);
            }
        }
        return ResponseResult.builder().data(dtoPageDTO).build();
    }
    /**
     * 根据房屋id,查询当前业主以及关联的所有户籍人员(包括户主自身)信息
     * @param id
     * @return
     */
    @Override
    public ResponseResult find(String id) {
        //拿到房屋信息
        LambdaQueryWrapper<Residence> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Residence::getId, id);
        lambdaQueryWrapper.eq(Residence::getEnabled, true);
        Residence residence = residenceDao.selectOne(lambdaQueryWrapper);
        //根据房屋信息，获取户籍成员和户主的信息
        LambdaQueryWrapper<Person> lambdaQueryWrapper2 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper2.eq(Person::getEnabled,true);
        lambdaQueryWrapper2.eq(Person::getPlaceId, residence.getId());
        List<Person> personList = personDao.selectList(lambdaQueryWrapper2);
        //处理户籍成员和户主居住地址
        List<PersonDto> personDtos = new ArrayList<>();
        for (Person person : personList) {
            PersonDto personDto = new PersonDto();
            BeanUtils.copyProperties(person,personDto);
            String abodeId = person.getAbodeId();//拿到住宅id
            Boolean inside2 = person.getInside2();//true是辖区内
            //拼接居住地址
            //辖区内情况
            if(StringUtils.hasText(abodeId) && inside2){
                LambdaQueryWrapper<SysCommunity> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(SysCommunity::getId,residence.getCommunityId());
                wrapper.eq(SysCommunity::getEnable,true);
                SysCommunity sysCommunity = sysCommunityDao.selectOne(wrapper);
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append(sysCommunity.getName());//社区名称
                LambdaQueryWrapper<SysPlot> wrapper2 = new LambdaQueryWrapper<>();
                wrapper2.eq(SysPlot::getId,residence.getPlotId());
                wrapper2.eq(SysPlot::getEnabled,true);
                SysPlot sysPlot = sysPlotDao.selectOne(wrapper2);
                stringBuilder.append(sysPlot.getName());//小区名称
                //住宅地址
                String address = residence.getAddress();
                if(StringUtils.hasText(address)){
                    if(address.contains("/")){
                        String[] split = address.split("/");
                        stringBuilder.append(split[0]);//楼房楼栋
                        stringBuilder.append(split[1]);//楼房单元
                    }else {
                        stringBuilder.append(address);//平房/别墅
                    }
                }
                //门牌号
                if(StringUtils.hasText(residence.getHouseNumber())){
                    stringBuilder.append(residence.getHouseNumber());
                }
                personDto.setAbode_address(stringBuilder.toString());
            }else {
                //辖区外 abodeId是空而且inside2是false
                //abodeId && inside2
                StringBuilder stringBuilder = new StringBuilder();
                String out2Province = person.getOut2Province();//省
                String out2City = person.getOut2City();//市
                String out2FullAddress = person.getOut2FullAddress();//辖区外居住详细地址
                stringBuilder.append(out2Province).append(out2City).append(out2FullAddress);
                personDto.setAbode_address(stringBuilder.toString());
            }
            personDtos.add(personDto);
        }
        return ResponseResult.builder().data(personDtos).build();
    }
    /**
     * 修改户籍情况
     * @return
     */
    @Override
    public ResponseResult updateSave(OccupancyDto occupancyDto, HttpServletRequest request) {
        String id = occupancyDto.getId();//获取住宅id
        int rows = 0;
        SysLog sysLog = new SysLog();
        StringBuilder stringBuilder = new StringBuilder();
        Residence residence = residenceDao.selectById(id);
        if (StringUtils.hasText(id)) {
            //此处备注不应该是住宅备注,而是户籍人员备注
            residenceDao.updateHouseRemark(id, occupancyDto.getHouseRemark());
            String houseRemark = occupancyDto.getHouseRemark();
            if(StringUtils.hasText(residence.getHouseRemark())){
                if(StringUtils.hasText(houseRemark)){
                    if(!houseRemark.equals(residence.getHouseRemark())){
                        stringBuilder.append("房屋户籍备注，修改前:").append(residence.getHouseRemark()).append(",修改后:").append(houseRemark);
                    }
                }else {
                    stringBuilder.append("房屋户籍备注，修改前:").append(residence.getHouseRemark()).append(",修改后:无");
                }
            }else {
                if(StringUtils.hasText(houseRemark)){
                    stringBuilder.append("房屋户籍备注，修改前:无").append(",修改后:").append(houseRemark);
                }
            }

            rows++;
        }
        List<Person> personList = occupancyDto.getPersonList();
        if (personList != null && personList.size() > 0) {
            for (Person person : personList) {
                if(Objects.isNull(person)){
                    return ResponseResult.builder().code(ResultCode.SYSTEM_ERROR.getCode()).message(ResultCode.SYSTEM_ERROR.getMessage()).build();
                }
                Person person1 = personDao.selectById(person.getId());
                int i = personDao.updateById(person);
                if(i>0){
                    rows++;
                }
                Person person2 = personDao.selectById(person.getId());
                if (StringUtils.hasText(person1.getPlaceremark())){
                    if(StringUtils.hasText(person2.getPlaceremark())){
                        if(!person1.getPlaceremark().equals(person2.getPlaceremark())){
                            stringBuilder.append("户籍人员备注，修改前:").append(person1.getPlaceremark()).append(",修改后:").append(person2.getPlaceremark());
                        }
                    }else {
                        stringBuilder.append("户籍人员备注，修改前:").append(person1.getPlaceremark()).append(",修改后:无");
                    }
                }else {
                    if(StringUtils.hasText(person2.getPlaceremark())){
                        stringBuilder.append("户籍人员备注，修改前:无").append(",修改后:").append(person2.getPlaceremark());
                    }
                }
            }
            sysLog.setDetails(stringBuilder.toString());
        }
        sysLog.setIncident("户籍信息");
        sysLog.setType("修改");
        sysLog.setValue("业务日志");
        sysLog.setCreateTime(new Date());
        sysLog.setIp(GetIp.getIpAddr(request));
        User user2 = (User) ShiroUtils.getSubject().getPrincipal();
        sysLog.setOperator(user2.getUsername());
        StringBuilder Builder = new StringBuilder();
        SysCommunity sysCommunity = sysCommunityDao.selectById(residence.getCommunityId());
        Builder.append(sysCommunity.getName());
        SysPlot sysPlot1 = sysPlotDao.selectById(residence.getPlotId());
        Builder.append(sysPlot1.getName()).append(residence.getAddress()).append(residence.getHouseNumber());
        sysLog.setContent("房屋地址:"+Builder);
        if(rows > 0){
            sysLog.setResult("成功");
        }else{
            sysLog.setResult("失败");
        }
        int insert = sysLogDao.insert(sysLog);
        if (insert > 0) {
            log.info("日志记录成功");
        } else {
            log.error("日志记录失败");
        }
        return rows > 0 ? ResponseResult.builder().build() : ResponseResult.builder().code(ResultCode.SYSTEM_ERROR.getCode()).message(ResultCode.SYSTEM_ERROR.getMessage()).build();
    }
    /**
     * 导出户籍列表
     * @param excelDto
     * @return
     */
    @Override
    public ResponseResult houseExcel(ExcelDto excelDto) {
        //创建一个目录
        File dir = new File(basePath);
        if(!dir.exists()){
            //目录如果不存在就创建一个
            dir.mkdirs();
        }
        //拿到所有符合入住人数范围的住宅id
        List<String> resids = new ArrayList<>();
        //如果输入了人数区间
        List<Map<String, Object>> maps;
        if (!Objects.isNull(excelDto)) {
            if (excelDto.getMinNumber() != null && excelDto.getMaxNumber() != null) {
                if(excelDto.getMinNumber() == 0){
                    List<Map<String, Object>> maps1 = residenceDao.countPlaceIdIsNull();
                    for (Map<String, Object> map : maps1) {
                        String abodeId = (String) map.get("place_id");
                        if(!StringUtils.hasText(abodeId)){//拿到全部为空的住宅id
                            String id = (String) map.get("id");
                            resids.add(id);
                        }
                    }
                }
                //先查询符合条件的住宅id,以及统计对应房屋的人数
                maps = residenceDao.countNumberPersonPlace(excelDto.getMinNumber(), excelDto.getMaxNumber());
                for (Map<String, Object> map : maps) {
                    String id = (String) map.get("id");
                    resids.add(id);
                }
            }
            if(excelDto.getIds() != null){
                List<String> ids = excelDto.getIds();
                ids.addAll(resids);
            }
        }
        //特殊处理楼房的详细地址
        String newDetailedAddress = null;
        if(excelDto != null && excelDto.getDetailedAddress() != null){
            if(excelDto.getDetailedAddress().size()>1){
                List<String> detailedAddress = excelDto.getDetailedAddress();
                newDetailedAddress  =  detailedAddress.get(0) +"/"+ detailedAddress.get(1);
            }else{
                List<String> detailedAddress = excelDto.getDetailedAddress();
                newDetailedAddress = detailedAddress.get(0);
            }
            excelDto.setAddress(newDetailedAddress);
        }
        //获取当前登陆人的信息
        User user = (User) ShiroUtils.getSubject().getPrincipal();
        LambdaQueryWrapper<SysUserRole> lambdaQueryWrapper5 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper5.eq(SysUserRole::getUserId, user.getId());
        SysUserRole sysUserRole = sysUserRoleDao.selectOne(lambdaQueryWrapper5);
        String roleKey = sysRoleDao.findByRoles(sysUserRole.getRoleId());
        //如果是街道管理员
        if ("street:admin".equals(roleKey)) {
            assert excelDto != null;
            excelDto.setCommunityIds(null);
        }else {
            //如果是社区管理员
            List<String> commnityIds = sysUserCommunityDao.commnityIds(user.getId());
            if (Objects.isNull(commnityIds) || commnityIds.size() <= 0) {
                return ResponseResult.builder().message("当前用户还没有任何社区权限").build();
            }
            assert excelDto != null;
            excelDto.setCommunityIds(commnityIds);
        }
        List<ExcelDto> excelDtos = personDao.houseFindByIdsExcel(excelDto);
        for (ExcelDto excelDto1 : excelDtos) {
            //处理业主姓名
            if(StringUtils.hasText(excelDto1.getOwnerId())){
                LambdaQueryWrapper<Person> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
                lambdaQueryWrapper1.eq(Person::getId,excelDto1.getOwnerId());
                lambdaQueryWrapper1.eq(Person::getEnabled,true);
                Person person = personDao.selectOne(lambdaQueryWrapper1);
                if(Objects.isNull(person)){
                    excelDto1.setPersonName(null);//业主姓名
                }else {
                    excelDto1.setPersonName(person.getName());//业主姓名
                }
            }else{
                excelDto1.setPersonName(null);
            }
            LambdaQueryWrapper<Person> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(Person::getPlaceId, excelDto1.getId());//房屋下的户籍人员
            lambdaQueryWrapper.eq(Person::getEnabled,true);
            //处理入住人员姓名
            List<Person> peoples = personDao.selectList(lambdaQueryWrapper);
            StringBuilder stringBuilder = new StringBuilder();
            if (!Objects.isNull(peoples) && peoples.size() > 0) {
                long num = 0L;
                for (Person people : peoples) {
                    if(people != null && StringUtils.hasText(people.getName())){
                        stringBuilder.append(people.getName()).append(" ");
                        num++;
                    }
                }
                excelDto1.setStayPersons(stringBuilder.toString());
                excelDto1.setStayPersonNumber(num);//入住人员数
            } else {
                excelDto1.setStayPersons(null);
                excelDto1.setStayPersonNumber(0L);
            }
        }
        try {
            Date date = new Date();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
            String format = simpleDateFormat.format(date);
            String filePathName = basePath + format + "户籍人员.xlsx";
            EasyExcel.write(filePathName, ExcelDto.class).sheet("户籍人员信息").doWrite(excelDtos);
            return ResponseResult.builder().data(filePathName).build();
        } catch (Exception ex) {
            log.info("写入住人员excel时出现异常！");
            log.info(ex.getMessage());
            return ResponseResult.builder().code(ResultCode.SYSTEM_ERROR.getCode()).message("系统读写文件时，出现异常").build();
        }
    }
}
